/**
 * Handles new connections by accepting a username and password.
 * Connection is then routed into normal game mode
 * TODO : 
 *  - Connect to database
 *  - Route Connection
 * @author bigredshoes03
 * @date - 10/1/2009
 */
package main_serv;

import java.io.IOException;
import java.net.Socket;
import java.sql.ResultSet;
import java.sql.SQLException;

import user.Session;

import database.SQL;

import networkcom.Opcode;
import networkcom.Packet;
import networkcom.PacketInputStream;
import networkcom.PacketOutputStream;

public class LoginHandler extends Thread implements Runnable{
	private Socket sock;
	private String username;
	private String password;
	private boolean rejected;

	public LoginHandler(Socket s){
		sock = s;
		rejected = false;
	}
	
	/**
	 * Handle login...
	 */
	public void run() {
		try {
			//build packet input and output streams
			PacketInputStream in = new PacketInputStream(sock.getInputStream());
			PacketOutputStream out = new PacketOutputStream(sock.getOutputStream());
			
			//Attempt to read username
			Packet p = in.readPacket();
			if(p.getOpcode()==Opcode.USERNAME){
				if(p.getStringData()!=null){
					username = p.getStringData();
				}else{
					reject(out,"Null username data");
				}
			}else{
				reject(out,"Invalid Opcode "+p.getOpcode()+" attempted to send username");
			}
			
			//Attempt to read password
			p = in.readPacket();
			if(p.getOpcode()==Opcode.PASSWORD && !rejected){
				if(p.getStringData()!=null){
					password = p.getStringData();
				}else{
					reject(out,"Null password data");
				}
			}else{
				reject(out,"Invalid Opcode "+p.getOpcode()+" attempted to send password");
			}
			
			//Check username and password against the user database
			if(!rejected){
				ResultSet set = SQL.getInstance().query("SELECT l.password,l.id, s.statId FROM login as l LEFT JOIN status as s on (l.id = s.playerId) WHERE l.username='"+username+"';");
				try {
						//Check login, if valid, send LOGIN_SUCCESSFUL opcode to the client
						set.next();
						if(set.getString("password").equals(password)){
							System.out.println("User logged in : "+username+" as "+((set.getInt("statId")==0)?"user":"admin"));
							out.writePacket(new Packet(Opcode.LOGIN_SUCCESSFUL,null));
							SQL.getInstance().query("UPDATE login SET logged=1 WHERE id="+set.getInt("id"));
							ClientHandler.getInstance().add(new Session(sock,set.getInt("id"),set.getInt("statId")));
						}else{
							//Reject due to invalid password
							
							reject(out,"Invalid user/pass ("+username+","+password+")");
						}
						//Reject due to non-existant username
				} catch (SQLException e) {reject(out,"Invalid username '"+username+"'"); e.printStackTrace();}
			}
		} catch (IOException e) {}	
	}

	/**
	 * Packaged function for sending a LOGIN_FAILED opcode
	 * prints a reasoning provided by the login flow
	 * @param out - stream to write to
	 * @param reason - reason for failure
	 * TODO : This should log reason for failure to a file
	 */
	private void reject(PacketOutputStream out, String reason){
		rejected = true;
		out.writePacket(new Packet(Opcode.LOGIN_FAILED,null));
		System.err.println("Login attempt failed ("+reason+") - closing connection...");
		try {
			sock.close();
		} catch (IOException e) {}
	}
}
